﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;

namespace GeometryProjectDll
{
    public class GeometryProject
    {
        private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();

        private static int coords_count_limit = 900;

        public static void ZsCoordToGDByWeb(List<Coord> coords, out List<Coord> outCoords)
        {
            if (coords.Count > coords_count_limit)
            {
                List<Coord> coords1 = coords.GetRange(0, coords_count_limit);
                List<Coord> coords1out;
                ZsCoordToGDByWeb(coords1, out coords1out);
                List<Coord> coords2 = coords.GetRange(coords_count_limit, coords.Count - coords_count_limit);
                List<Coord> coords2out;
                ZsCoordToGDByWeb(coords2, out coords2out);
                outCoords = new List<Coord>();
                outCoords.AddRange(coords1out);
                outCoords.AddRange(coords2out);
                return;
            }
            string baseUrl = "http://11.1.1.11:6080/arcgis/rest/services/Utilities/Geometry/GeometryServer/project";
            string inSR = "{ \"wkt\" :\"PROJCS[\\\"ZSprojection\\\",GEOGCS[\\\"Zhongshan_1954change(Geo)\\\",DATUM[\\\"<custom>\\\",SPHEROID[\\\"<custom>\\\",6378317.0,298.3]],PRIMEM[\\\"<custom>\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Gauss_Kruger\\\"],PARAMETER[\\\"False_Easting\\\",500000.0],PARAMETER[\\\"False_Northing\\\",0.0],PARAMETER[\\\"Central_Meridian\\\",113.3666666666667],PARAMETER[\\\"Scale_Factor\\\",1.0],PARAMETER[\\\"Latitude_Of_Origin\\\",0.0],UNIT[\\\"Meter\\\",1.0]]\"}";
            string outSR = "{\"wkt\" :\"PROJCS[\\\"WGS_1984_Web_Mercator_Auxiliary_Sphere\\\",GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137.0,298.257223563]],PRIMEM[\\\"Greenwich\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Mercator_Auxiliary_Sphere\\\"],PARAMETER[\\\"False_Easting\\\",0.0],PARAMETER[\\\"False_Northing\\\",0.0],PARAMETER[\\\"Central_Meridian\\\",0.0],PARAMETER[\\\"Standard_Parallel_1\\\",0.0],PARAMETER[\\\"Auxiliary_Sphere_Type\\\",0.0],UNIT[\\\"Meter\\\",1.0],AUTHORITY[\\\"EPSG\\\",3857]]\"}";
            string points = "";
            foreach(var coord in coords)
            {
                if (points == "")
                    points = "{\"x\" : " + coord.X + ", \"y\" : " + coord.Y + "}";
                else
                    points += ",{\"x\" : " + coord.X + ", \"y\" : " + coord.Y + "}";
            }
            string geometries = "{ \"geometryType\" : \"esriGeometryPoint\", \"geometries\" : [ " + points + " ]}";
            string f = "json";
            string transformForward = "true";
            string vertical = "false";
            string url = makeUrl(baseUrl, inSR, outSR, geometries, transformForward, vertical, f);
            string data = getDataFromWeb(url);
            if (data == "")
            {
                outCoords = new List<Coord>();
                Logger.Error("ZsCoordToGDByWeb GDCoordToZsByWeb error coords.count:" + coords.Count);
                return;
            }
            GeometryProjectResult r = JsonConvert.DeserializeObject<GeometryProjectResult>(data); //反序列化
            outCoords = new List<Coord>();
            foreach (var g in r.geometries)
                outCoords.Add(new Coord(g.x + 662, g.y - 347));
        }

        public static void GDCoordToZsByWeb(List<Coord> coords, out List<Coord> outCoords)
        {
            if (coords.Count > coords_count_limit)
            {
                List<Coord> coords1 = coords.GetRange(0, coords_count_limit);
                List<Coord> coords1out;
                GDCoordToZsByWeb(coords1, out coords1out);
                List<Coord> coords2 = coords.GetRange(coords_count_limit, coords.Count - coords_count_limit);
                List<Coord> coords2out;
                GDCoordToZsByWeb(coords2, out coords2out);
                outCoords = new List<Coord>();
                outCoords.AddRange(coords1out);
                outCoords.AddRange(coords2out);
                return;
            }
            string baseUrl = "http://11.1.1.11:6080/arcgis/rest/services/Utilities/Geometry/GeometryServer/project";
            string outSR = "{ \"wkt\" :\"PROJCS[\\\"ZSprojection\\\",GEOGCS[\\\"Zhongshan_1954change(Geo)\\\",DATUM[\\\"<custom>\\\",SPHEROID[\\\"<custom>\\\",6378317.0,298.3]],PRIMEM[\\\"<custom>\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Gauss_Kruger\\\"],PARAMETER[\\\"False_Easting\\\",500000.0],PARAMETER[\\\"False_Northing\\\",0.0],PARAMETER[\\\"Central_Meridian\\\",113.3666666666667],PARAMETER[\\\"Scale_Factor\\\",1.0],PARAMETER[\\\"Latitude_Of_Origin\\\",0.0],UNIT[\\\"Meter\\\",1.0]]\"}";
            string inSR = "{\"wkt\" :\"PROJCS[\\\"WGS_1984_Web_Mercator_Auxiliary_Sphere\\\",GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137.0,298.257223563]],PRIMEM[\\\"Greenwich\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Mercator_Auxiliary_Sphere\\\"],PARAMETER[\\\"False_Easting\\\",0.0],PARAMETER[\\\"False_Northing\\\",0.0],PARAMETER[\\\"Central_Meridian\\\",0.0],PARAMETER[\\\"Standard_Parallel_1\\\",0.0],PARAMETER[\\\"Auxiliary_Sphere_Type\\\",0.0],UNIT[\\\"Meter\\\",1.0],AUTHORITY[\\\"EPSG\\\",3857]]\"}";
            string points = "";
            foreach (var coord in coords)
            {
                if (points == "")
                    points = "{\"x\" : " + (coord.X - 662) + ", \"y\" : " + (coord.Y + 347) + "}";
                else
                    points += ",{\"x\" : " + (coord.X - 662) + ", \"y\" : " + (coord.Y + 347) + "}";
            }
            string geometries = "{ \"geometryType\" : \"esriGeometryPoint\", \"geometries\" : [ " + points + " ]}";
            string f = "json";
            string transformForward = "true";
            string vertical = "false";
            string url = makeUrl(baseUrl, inSR, outSR, geometries, transformForward, vertical, f);
            string data = getDataFromWeb(url);
            if (data == "")
            {
                outCoords = new List<Coord>();
                Logger.Error("GDCoordToZsByWeb error coords.count:" + coords.Count);
                return;
            }
            GeometryProjectResult r = JsonConvert.DeserializeObject<GeometryProjectResult>(data); //反序列化
            outCoords = new List<Coord>();
            foreach (var g in r.geometries)
                outCoords.Add(new Coord(g.x, g.y));
        }

        public static void ZsCoordToGDByWeb(double x, double y, out double gdX, out double gdY)
        {
            List<Coord> coords = new List<Coord>();
            List<Coord> outcoords;
            coords.Add(new Coord(x, y));
            ZsCoordToGDByWeb(coords, out outcoords);
            if (outcoords.Count > 0)
            {
                gdX = outcoords[0].X;
                gdY = outcoords[0].Y;
            }
            else
            {
                gdX = 0;
                gdY = 0;
            }
        }

        private static string makeUrl(string baseUrl, string inSR, string outSR, string geometries, string transformForward,
            string vertical, string f)
        {
            Encoding encoding = Encoding.UTF8;
            string url = baseUrl + '?' + "inSR=" + HttpUtility.UrlEncode(inSR, encoding)
                + '&' + "outSR=" + HttpUtility.UrlEncode(outSR, encoding)
                + '&' + "geometries=" + HttpUtility.UrlEncode(geometries, encoding)
                + '&' + "f=" + HttpUtility.UrlEncode(f, encoding)
                + '&' + "transformForward=" + HttpUtility.UrlEncode(transformForward, encoding)
                + '&' + "vertical=" + HttpUtility.UrlEncode(vertical, encoding);
            return url;
        }

        private static string getDataFromWeb(string url)
        {
            try
            {
                string resultstring = "";
                Encoding encoding = Encoding.UTF8;
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);//这里的url指要获取的数据网址
                request.Method = "GET";
                request.Accept = "text/html, application/xhtml+xml, */*";
                request.ContentType = "application/json";
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
                {
                    resultstring = reader.ReadToEnd();
                }
                return resultstring;
            }
            catch(Exception e)
            {
                Logger.Error("getDataFromWeb error:" + e.Message + ";" + e.StackTrace);
                throw e;
            }
        }
    }
}
